/*******************************************************************************
 * SVN­Versioning-Information:
 * ­­­­­­­­­­­­­­­­­­­­­­­­
 * $LastChangedRevision: 6 $
 * $LastChangedBy: c.a.duevel $
 * $LastChangedDate: 2009-08-26 15:12:37 +0000 (Wed, 26 Aug 2009) $
 * $HeadURL: http://robofight.googlecode.com/svn/trunk/ClientJava/src/de/hft_stuttgart/robofight/client/java/JRunningGame.java $
 ******************************************************************************/
package de.hft_stuttgart.robofight.client.java;

import de.hft_stuttgart.botwar.common.commands.ChatCmd;
import de.hft_stuttgart.botwar.common.commands.Cmd;
import de.hft_stuttgart.botwar.common.commands.GameOverCmd;
import de.hft_stuttgart.botwar.common.commands.KickCmd;
import de.hft_stuttgart.botwar.common.commands.MoveCmd;
import de.hft_stuttgart.botwar.common.commands.ShootCmd;
import de.hft_stuttgart.botwar.common.commands.StartGameCmd;
import de.hft_stuttgart.botwar.common.interfaces.IRemotePlayer.MODE;
import de.hft_stuttgart.botwar.common.models.GameResultInfo;
import de.hft_stuttgart.botwar.common.models.GameResultInfo.Result;
import de.hft_stuttgart.botwar.common.models.Position;
import de.hft_stuttgart.botwar.common.models.RobotInfo;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 *
 * @author ralf.dauenhauer@gmx.de, michael.rieker@web.de
 */
public class JRunningGame {

    private MoveCmd mc;
    private ShootCmd sc;
    private GameOverCmd goc = null;
    private ChatCmd cc;
    private Map<Integer, JRobot> allRobots = new HashMap<Integer, JRobot>();
    private List<Integer> playerRobots = new ArrayList<Integer>();
    private List<ChatCmd> gameLobbyChatList = new ArrayList<ChatCmd>();
    private JPlayer player;
    private boolean isRunning = false;
    private String winnerId = null;
    private String mapName;
    private int gameID;
    private Map<String, Integer> playerMap = new HashMap<String, Integer>();

    /**
     * creates a JRunningGame instance.
     * @param player needs the jPlayer
     */
    public JRunningGame(final JPlayer player) {
        this.player = player;
    }

    /**
     * initializes a game.
     * @throws java.rmi.RemoteException throws RemoteException
     */
    public final void initGame() throws RemoteException {
        gameID = player.getGameID();
        mapName = player.getPlayer().getGameInfo(gameID).getMapName();
        int color = 0;

        // iterate over all players in a given game
        for (String playerName : player.getPlayer().getGameInfo(
                gameID).getPlayers()) {

            playerMap.put(playerName, color);
            for (Iterator<RobotInfo> it = player.getPlayer().getGameInfo(
                    gameID).getRobotInfos(
                    playerName).iterator(); it.hasNext();) {

                RobotInfo ri = it.next();
                allRobots.put(ri.getRobotID(), new JRobot(
                        player.getPlayer().getPosition(
                        ri.getRobotID()),
                        color,
                        ri.getRobotID(),
                        ri.getEnergy(),
                        ri.getChassis().getName(),
                        ri.getShield().getName(),
                        ri.getArmament().getName()));
            }
            color++;
        }
    }

    /**
     * returns the name of the current map.
     * @return mapName name of current map
     */
    public final String getMapName() {
        return this.mapName;
    }

    /**
     * returns a Map<PlayerName, Color>.
     * @return playerMap map of players
     */
    public final Map<String, Integer> getPlayerMap() {
        return this.playerMap;
    }

    /**
     * returns the gameOverCommand
     * @return goc
     */
    public final GameOverCmd getGameOverCommand() {
        return this.goc;
    }

    /**
     * polls the rmi server.
     * @throws java.rmi.RemoteException throws RemoteException
     */
    public final void checkCommand() throws RemoteException {
        List<Cmd> commands = player.getPlayer().poll();
        for (Cmd cmd : commands) {
            //Move-Command
            if (cmd instanceof MoveCmd) {
                mc = (MoveCmd) cmd;
                allRobots.get(mc.getRobotID()).setNewPos(mc.getTarget());
            // Shoot-Command
            } else if (cmd instanceof ShootCmd) {
                sc = (ShootCmd) cmd;
                allRobots.get(sc.getAttackRobotId()).setShootTo(
                        sc.getTargetRobotId());

                allRobots.get(sc.getTargetRobotId()).setHealth(
                        sc.getTargetRobotEnergyLeft());
            } // Chat-Command
            else if (cmd instanceof ChatCmd) {
                cc = (ChatCmd) cmd;
                switch (cc.getChatType()) {
                    case GAMELOBBY:
                        gameLobbyChatList.add(cc);
                        break;
                    case PRIVATE:
                        gameLobbyChatList.add(cc);
                        break;
                    default:
                }
            } // GameOver-Command
            else if (cmd instanceof GameOverCmd) {
                goc = (GameOverCmd) cmd;
                player.setGameResultList(goc);
                this.playerMap = null;
                this.isRunning = false;
            } //StartGame-Command
            else if (cmd instanceof StartGameCmd) {
                this.isRunning = true;
            } // Kick-Cmd, --> GameCrashed
            else if (cmd instanceof KickCmd) {
                List<GameResultInfo> gr = new ArrayList<GameResultInfo>();
                gr.add(new GameResultInfo("game crashed", Result.DRAW, 0));
                goc = new GameOverCmd(gr);
                this.isRunning = false;
                player.setGameResultList(goc);
                this.playerMap = null;
            }
        }
    }

    /**
     * set new Target Position.
     * @param robotId needs the bot id to set new target
     * @param x the target x value
     * @param y the target y value
     * @return boolean true if the bot is one of the player
     * @throws java.rmi.RemoteException throws RemoteException
     */
    public final boolean setTarget(final int robotId, final int x, final int y)
            throws RemoteException {
        try {
            player.getPlayer().setTarget(robotId, new Position(x, y));
            return true;
        } catch (IllegalStateException exp) {
            return false;
        } catch (IllegalArgumentException exp) {
            return false;
        } catch (UnsupportedOperationException exp) {
            return false;
        }
    }

    /**
     * set new Mode for robotId.
     * @param robotId needs the bot id to set the mode
     * @param mode sets the mode of a bot
     * @throws java.rmi.RemoteException throws RemoteException
     */
    public final void setMode(final int robotId, final int mode)
            throws RemoteException {

        if (mode == 0) {
            player.getPlayer().setMode(robotId, MODE.AGGRESSIVE);
        }
        if (mode == 1) {
            player.getPlayer().setMode(robotId, MODE.STANDARD);
        }
    }

    /**
     * returns a Map of robots.
     * @return Map
     */
    public final Map<Integer, JRobot> getRobots() {
        return this.allRobots;
    }

    /**
     * returns only robots for the RemotePlayer.
     * @return playerRobots player robots
     */
    public final List<Integer> getPlayerRobots() {
        return playerRobots;
    }

    /**
     * Returns the position for a given robotId.
     * @param robotId needs the bot id to get the position
     * @return player.getPlayer().getPosition(robotId) position of a bot
     * @throws java.rmi.RemoteException throws RemoteException
     */
    public final Position getPosition(final int robotId)
            throws RemoteException {

        return player.getPlayer().getPosition(robotId);
    }

    /**
     * Returns boolean if a game is running.
     * @return isRunning return if a game is running
     */
    public final boolean getIsRunning() {
        return this.isRunning;
    }

    /**
     * Returns the winner id.
     * @return winnerID returns the winner id
     */
    public final String getWinnerId() {
        return this.winnerId;
    }

    /**
     * returns the list of all robots.
     * @return allRobots all robots
     */
    public final Map<Integer, JRobot> getAllRobots() {
        return this.allRobots;
    }

    /**
     * returns the game lobby chat messages.
     * @return gameLobbyChatList returns a list contains all messages in lobby
     */
    public final List<ChatCmd> getGameLobbyChatMsg() {
        return this.gameLobbyChatList;
    }

    /**
     * sends a game chat message
     * @param message string with the messsage
     * @throws java.rmi.RemoteException
     */
    public final void sendGameChatMessage(final String message) throws
            RemoteException {
        player.sendGameChatMsg(message);
    }

    /**
     * clear all chatMessages
     */
    public final void cleanChatMessages() {
        this.gameLobbyChatList.clear();
    }
}
